//
// Created by deng on 18-11-28.
//

#include <iostream>
#include <chrono>
#include <cstring>

#include "solution.h"

namespace doudizhu_endgame {

#define CLI

//
//输入不带空格，'10'用'0'（零）代替
//示例：[大王 A Q Q J J 10 9 9 9 4 4]
//输入：zaqqjj0999844
//
    void Solution::start() {
        std::cout << "输入不带空格,'10'用'0'（零）代替" << "\n";
        std::cout << "如：[大王 小王 2 A 10 9 9 9 4]" << "\n";
        std::cout << "输入：zy2a09994" << "\n";
        std::cout <<"地主先出"<<"\n";
        std::cout << "------------------------------" << "\n";

#ifdef CLI
        std::string l = input_stdin("输入地主手牌:");
        std::string f = input_stdin("输入农民手牌:");
        std::cout << "------------------------------" << "\n";
#else
        std::string l{"zaqqjj0999844"};
        std::string f{"y22aa0886633"};
#endif //CLI

        CardSet lord, farmer;
        //加载双方手牌
        lord.from_string(l);
        farmer.from_string(f);

        using namespace std::chrono;
        steady_clock::time_point start = steady_clock::now();
        //todo 核心 开始dfs
        TreeNode *root = engine_->search(lord, farmer);
        //经过dfs构建搜索树后，root下面都是地主能赢的节点
        steady_clock::time_point end = steady_clock::now();

        duration<double> time_span = duration_cast<duration<double>>(end - start);
        std::cout << GREEN << "nodes calculated: " << RESET << engine_->nodes_searched() << "\n";
        std::cout << GREEN << "search time: " << RESET << time_span.count() << GREEN << " seconds.\n";
        std::cout << GREEN << "transposition table hit rate: " << RESET << engine_->hash_hit_rate() << "%\n\n";
        //地主出赢的策略
        if (root->score == 1 && !root->child.empty()) {
            std::cout << BOLDGREEN << "出:["
                      << root->child[0]->last_move->hand.str() << "]" << RESET << "\n";

#ifdef CLI
            process_result(root->child[0]);
#endif //CLI

        } else {//地主没法必赢
            std::cout << RED << "无法取胜" << RESET << "\n";
        }
    }

/**
 * 输出地主对应的出牌路径,node->child是地主
 * @param node 农民
 */
    void Solution::process_result(TreeNode *node) {
        //记录对手-农民出的牌,用于缓存命中时构建地主的搜索树
        Pattern *last = nullptr;

        bool search = true;
        while (!node->child.empty() && search) {
            CardSet hand;
            hand.from_string(input_stdin("输入农民出牌:"));

            for (auto child: node->child) {
                //路径匹配
                if (child->last_move->hand == hand) {
                    //last表示农民出的牌
                    last = child->last_move;
                    if (!child->child.empty()) {//还有农民节点
                        //地主出牌路径,更新农民节点到下一层
                        node = child->child[0];
                        std::cout << "------------------------------" << "\n";
                        std::cout << BOLDGREEN << "地主出: [" << node->last_move->hand.str() << "]" << RESET << "\n";
                        std::cout << "currt loard hand: [" << node->lord.str() << "]\n";
                        std::cout << "currt farmer hand:[" << node->farmer.str() << "]\n";
                        std::cout << "currt turn:[" << (int)(node->turn) << "]\n";
                        std::cout << "currt score:[" << (int)(node->score) << "]\n";

                    } else {//到叶子节点了，可能是置换表中的节点
                        search = false;
                    }

                } else {
                    //find next match
                }
            }
        }

        std::cout << "-------------退出process_result循环-----------------=" << search << "\n";
//        std::cout << BOLDGREEN << "出: [" << node->last_move->hand.str() << "]" << RESET << "\n";
        std::cout << "currt loard hand: [" << node->lord.str() << "]\n";
        std::cout << "currt farmer hand:[" << node->farmer.str() << "]\n";

        //此处的场景，dfs的时候，如果用的缓存节点，此时直接返回分值，没有构建树,所以需要当前的农民节点+农民要出的牌构建新的搜索树
        if (!node->lord.empty() && last != nullptr) {
            std::cout << "-------------hash碰撞了，构建树-----------------=" << search << "\n";
            restart_search(node, last);

        } else {
            //finsh process
        }
    }

/**
 * 根据农民节点和农民要出的牌，构建下一层的地主搜索树
 * @param node 农民节点
 * @param last 农民要出的牌
 */
    void Solution::restart_search(TreeNode *node, Pattern *last) {
        CardSet lord = node->lord;
        CardSet farmer = node->farmer;
        farmer.remove(last->hand);
        Pattern last_{last->power, last->type, last->hand};
        std::cout << "restart search..." << "\n";

        reset_engine();
        //re是地主的节点
        TreeNode *re = engine_->search(lord, farmer, &last_);

        if (!re->child.empty()) {
            std::cout << "出: [" << re->child[0]->last_move->hand.str() << "]\n";
            //地主出牌了，等待农民出牌
            process_result(re->child[0]);

        } else {
            std::cout << "无法取胜" << "\n";
        }
    }

    std::string Solution::input_stdin(const char *prompt) {
        printf("%s\n", prompt);

        char *buff = new char[50];

        buff = fgets(buff, 50, stdin);
        size_t len = strlen(buff);
        if (len > 1) {
            buff[len - 1] = '\0';

        } else {
            //input is a 'Pass'
        }

        std::string string(buff);
        delete[] buff;

        return string;
    }

    void Solution::reset_engine() {
        delete engine_;
        engine_ = new Negamax;
    }

    void Solution::set_time_out() {
        //
    }

} //namespace doudizhu_endgame
